package com.efast.cafe.framework.mybatis.interceptor;

import java.sql.Connection;
import java.util.Map;
import java.util.Properties;

import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;

import com.efast.cafe.framework.bean.TemplateParameter;
import com.efast.cafe.framework.mybatis.util.PluginUtil;

@SuppressWarnings("all")
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) })
@Component
public class SelectTemplateInterceptor implements Interceptor {
	private Properties properties;

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		StatementHandler handler = (StatementHandler) PluginUtil.processTarget(invocation.getTarget());
		MetaObject metaObject = SystemMetaObject.forObject(handler);
		BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
		Object paramObj = boundSql.getParameterObject();
		TemplateParameter parameter = null;
		if (paramObj instanceof Map) {
			Map mmp = (Map) paramObj;
			Map<String, Object> map = null;
			if (mmp.containsKey("parameter") && mmp.get("parameter") != null && mmp.get("parameter") instanceof TemplateParameter) {
				parameter = (TemplateParameter) mmp.get("parameter");
				if(parameter!=null)
					map = parameter.getMap();
			} else {
				return invocation.proceed();
			}
			MappedStatement ms = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
			if (map != null && map.size() != 0) {
				for (String key : map.keySet()) {
					((Map) paramObj).put(key, map.get(key));
				}
			}
			if (parameter != null && (parameter.getPagenation() == null || parameter.getPagenation() == 0) && parameter.getMaxRowsInNoPage() != null) {
				String sql = getPageSql(parameter.getMaxRowsInNoPage(), boundSql.getSql());
				metaObject.setValue("delegate.boundSql.sql", sql);
			}

		}
		return invocation.proceed();
	}

	@Override
	public Object plugin(Object target) {
		if (target instanceof StatementHandler) {
			return Plugin.wrap(target, this);
		} else {
			return target;
		}
	}

	@Override
	public void setProperties(Properties properties) {
		this.properties = properties;

	}

	private String getPageSql(Integer maxRowsInNoPage, String sql) {
		StringBuffer sqlBuffer = new StringBuffer(sql);
		sqlBuffer.append(" limit ").append("0").append(",").append(maxRowsInNoPage);
		return sqlBuffer.toString();
	}
}
